package xssh

import (
	"context"
	"io/ioutil"
	"net"

	"golang.org/x/crypto/ssh"
)

// ViaSSHDialer ..
type ViaSSHDialer struct {
	Client *ssh.Client
	_      *context.Context
}

// // SSHKeyParmas ..
// type SSHKeyParmas struct {
// 	Addr    string
// 	User    string
// 	KeyFile string
// }

// // SSHPwdParams ..
// type SSHPwdParams struct {
// 	Addr     string
// 	User     string
// 	Password string
// }

// SSHConf ..
type SSHConf struct {
	Addr     string
	User     string
	KeyFile  string
	Password string
}

// ToString 生成字符串
func (sc *SSHConf) ToString() string {
	return sc.Addr + sc.User + sc.KeyFile + sc.Password
}

// Dial ..
func (_self *ViaSSHDialer) DialContext(context context.Context, addr string) (net.Conn, error) {
	return _self.Client.Dial("tcp", addr)
}

// Dial ..
func (_self *ViaSSHDialer) Dial(addr string) (net.Conn, error) {
	return _self.Client.Dial("tcp", addr)
}

func startDial(addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
	return ssh.Dial("tcp", addr, config)
}

// SSHConnWithKey 通过密钥进行ssh连接
func SSHConnWithKey(params SSHConf) (*ssh.Client, error) {
	keyContent, err := ioutil.ReadFile(params.KeyFile)
	if err != nil {
		return nil, err
	}

	signer, err := ssh.ParsePrivateKey(keyContent)
	if err != nil {
		return nil, err
	}

	config := &ssh.ClientConfig{
		User: params.User,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			return nil
		},
	}

	return startDial(params.Addr, config)
}

// SSHConnWithPassword 通过密码进行ssh连接
func SSHConnWithPassword(params SSHConf) (*ssh.Client, error) {
	config := &ssh.ClientConfig{
		User: params.User,
		Auth: []ssh.AuthMethod{
			ssh.Password(params.Password),
		},
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			return nil
		},
	}

	return startDial(params.Addr, config)
}
